package com.etone.smartAudit.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.etone.smartAudit.dto.jiutian.TitlesDTO;
import com.etone.smartAudit.error.CustomParameterizedException;
import com.etone.smartAudit.onlyoffice.util.JiuTianURLConstant;
import com.etone.smartAudit.utils.Base64Util;
import com.etone.smartAudit.utils.HttpUtil;
import com.etone.smartAudit.vo.jiutian.CommonVO;
import com.etone.smartAudit.vo.jiutian.OcrPdfVO;
import com.etone.smartAudit.vo.jiutian.OcrWordVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;

@Service
@Slf4j
public class JiuTianService {


    @Autowired
    private RestTemplate restTemplate;

    /**
     * 调用九天OCR通用文字识别接口
     * @param file
     * @return
     */
    public Object ocrDiscernWork(MultipartFile file) throws IOException {
        String url = JiuTianURLConstant.JIUTIAN_OCRWORK_URL;
        Map<String, Object> param = new HashMap<>();
        BASE64Encoder encoder = new BASE64Encoder();
        String encode = encoder.encode(file.getBytes());
        param.put("image", encode);
        Object send = send(param, url);
        log.info("返回值结果为{}", send);
        return send;
    }

    /**
     * 调用九天表格识别接口
     * @param file
     * @return
     */
    public Object sheetocr(MultipartFile file) throws IOException {
        String url = JiuTianURLConstant.JIUTIAN_SHEETOCR_URL;
        Map<String, Object> param = new HashMap<>();
        BASE64Encoder encoder = new BASE64Encoder();
        String encode = encoder.encode(file.getBytes());
        param.put("image", encode);
        Object send = send(param, url);
        log.info("返回值结果为{}", send);
        return send;
    }

    /**
     * 调用九天文本关键字提取
     * @param text
     * @return
     */
    public Object getKeywords(String text){
        String url = JiuTianURLConstant.JIUTIAN_GETKEYWORDS_URL;
        Map<String, Object> param = new HashMap<>();
        param.put("input_text", text);
        Object send = send(param, url);
        log.info("返回值结果为:{}", send);
        return send;
    }

    /**
     * 命名实体类识别
     * @param text
     * @return
     */
    public Object bertner(String text){
        String url = JiuTianURLConstant.JIUTIAN_BERTNER_URL;
        Map<String, Object> param = new HashMap<>();
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        param.put("textId", uuid);
        param.put("text", text);
        Object send = send(param, url);
        log.info("返回值结果为:{}", send);
        return send;
    }

    /**
     * 调用九天词相关服务
     * @param type
     * @param word1
     * @param word2
     * @return
     */
    public Object related(Integer type,String word1,String word2){
        String url;
        Map<String, Object> param = new HashMap<>();
        switch (type) {
            case 1:
                url = JiuTianURLConstant.JIUTIAN_WORDEMY_RELATED_URL;
                param.put("word", word1);
                param.put("top_n", 10);
                param.put("is_group", 0);
                return send(param, url);
            case 2:
                url = JiuTianURLConstant.JIUTIAN_WORDEMY_SIMI_URL;
                param.put("w1", word1);
                param.put("w2", word2);
                return send(param, url);
            case 3:
                url = JiuTianURLConstant.JIUTIAN_WORDEMY_GETWV_URL;
                param.put("word", word1);
                return send(param, url);
            default:
                param.put("result_code", "400");
                param.put("result_desc", "ERROR - 输入的功能类型有误！");
                param.put("result_data", Collections.EMPTY_LIST);
                return param;
        }
    }

    /**
     * 调用九天实体关系提取接口
     * @param text
     * @return
     */
    public Object relationExtract(String text){
        String url = JiuTianURLConstant.JIUTIAN_RELATIONEXTRACT_URL;
        Map<String, Object> param = new HashMap<>();
        param.put("text", text);
        Object send = send(param, url);
        log.info("返回值结果为:{}", send);
        return send;
    }

    /**
     * 调用九天多语言分词接口
     * @param word
     * @return
     */
    public Object wordCut(String word){
        String url = JiuTianURLConstant.JIUTIAN_WORDCUT_URL;
        Map<String, Object> param = new HashMap<>();
        param.put("word", word);
        Object send = send(param, url);
        log.info("返回值结果为:{}", send);
        return send;
    }

    /**
     * 调用九天文本相似度识别接口
     * @param titles
     * @return
     */
    public Object titleSimilarity(List<TitlesDTO> titles){
        String url = JiuTianURLConstant.JIUTIAN_TITLESIMILARITY_URL;
        Map<String, Object> param = new HashMap<>();
        param.put("title_list", titles);
        Object send = send(param, url);
        log.info("返回值结果为:{}", send);
        return send;
    }

    /**
     * 调用百度OCR文字提取接口
     * @param file
     * @param type
     * @param page
     * @param urlAdd
     * @return
     */
    public CommonVO<String> accurateBasic(MultipartFile file, Integer type, Integer page, String urlAdd){
        String url = JiuTianURLConstant.BAIDU_ACCURATEBASIC_URL;
        Object obj = baiduApi(file, type, page, urlAdd, url);
        JSONObject jsonObject = JSONObject.parseObject(obj.toString());
        String string = jsonObject.getString("words_result");
        JSONArray objects = JSONObject.parseArray(string);
        String text = "";
        for (int i = 0; i < objects.size(); i++) {
            String words = objects.getJSONObject(i).getString("words");
            text += words + "\n";
        }
        return new CommonVO<>("200","success",text);
    }

    //调用九天API接口
    public Object send(Map<String, Object> param, String url) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json;charset=UTF-8");
        HttpEntity<String> formEntity = new HttpEntity<String>(JSON.toJSONString(param), headers);
        log.info("调用参数为:{}", param);
        ResponseEntity<String> exchange = restTemplate.exchange(url,
                HttpMethod.POST, formEntity, String.class);
        JSONObject body = JSONObject.parseObject(exchange.getBody());
        log.info("返回数据为:{}", body);
        return body;
    }

    //百度api接口
    public String getToken() {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json;charset=UTF-8");
        HttpEntity<String> formEntity = new HttpEntity<String>(headers);
        ResponseEntity<String> exchange = restTemplate.exchange("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials" +
                        "&client_id=" + JiuTianURLConstant.API_KEY + "&client_secret=" + JiuTianURLConstant.SECRET_KEY,
                HttpMethod.POST, formEntity, String.class);
        JSONObject body = JSONObject.parseObject(exchange.getBody());
        String accessToken = body.getString("access_token");
        log.info("返回值结果为{}", body);
        log.info("accessToken{}", accessToken);
        return accessToken;
    }

    //百度文字识别和印章识别接口
    public Object baiduApi(MultipartFile file, Integer type, Integer page, String urlAdd, String url) {
        try {
            String encode = Base64Util.encode(file.getBytes());
            String imgParam = URLEncoder.encode(encode, "UTF-8");
            String param;
            switch (type) {
                case 1:
                    param = "image=" + imgParam;
                    break;
                case 2:
                    param = "pdf_file=" + imgParam + "&pdf_file_num=" + page;
                    break;
                default:
                    param = "url=" + urlAdd;
            }
            // 注意这里仅为了简化编码每一次请求都去获取access_token，线上环境access_token有过期时间， 客户端可自行缓存，过期后重新获取。
            String accessToken = getToken();
            log.info("请求token{}:",accessToken);
            return HttpUtil.post(url, accessToken, param);
        } catch (Exception e) {
            return new CommonVO<>("500","请求失败",e.getMessage());
        }
    }

    public CommonVO<List<OcrPdfVO>> accurateBasicAll(MultipartFile file) {
        List<OcrPdfVO> list = new ArrayList<>();
        try {
            PDDocument pdDocument = PDDocument.load(file.getInputStream());
            int pages = pdDocument.getNumberOfPages();
            String result = "";
            for (int i = 1; i <= pages; i++) {
                result = accurateBasic(file, 2, i, null).getResultData();
                OcrPdfVO vo = new OcrPdfVO();
                vo.setPageNum(i);
                vo.setResult(result);
                list.add(vo);
            }
        } catch (IOException e) {
            throw new CustomParameterizedException(e.getMessage());
        }
        return new CommonVO<>("200","success",list);
    }

    public CommonVO<List<OcrWordVO>> baiduWork(MultipartFile file) {
        // 请求url
        String url = JiuTianURLConstant.BAIDU_FROM_URL;
        try {
            String imgStr = Base64Util.encode(file.getBytes());
            String imgParam = URLEncoder.encode(imgStr, "UTF-8");
            String param = "image=" + imgParam;
            // 注意这里仅为了简化编码每一次请求都去获取access_token，线上环境access_token有过期时间， 客户端可自行缓存，过期后重新获取。
            String accessToken = getToken();
            String result = HttpUtil.post(url, accessToken, param);
            //获取处理 表格数据。
            String formsResult = JSON.parseObject(result).getJSONArray("forms_result").get(0).toString();
            String body = JSON.parseObject(formsResult).getString("body");
            //获取的数据
            List<OcrWordVO> vos = JSON.parseArray(body, OcrWordVO.class);
//            //处理完后的数据
//            List<OcrWordVO> codeVO = new ArrayList<>();
//            List<OcrWordVO> priceVO = new ArrayList<>();
            //定额编码
//            Integer indexNum = 0;
            //定额价格
//            Integer indexPrice = 0;
//            if (vos.size()>0){
//                for (OcrWordVO vo : vos) {
//                    if ("定额编码".equals(vo.getWords())){
//                        indexNum = vo.getRow();
//                    }
//                    if ("技工".equals(vo.getWords())){
//                        indexPrice = vo.getRow();
//                    }
//                    if (vo.getRow().equals(indexNum)){
//                        codeVO.add(vo);
//                    }else if (vo.getRow().equals(indexPrice)){
//                        priceVO.add(vo);
//                    }
//                }
//            }
//            //定额编码和定额价格对应
//            List<Map<String,Double>> maps = new ArrayList<>();
//            int index = 1;
//            for (OcrWordVO wordVO : priceVO) {
//                if (!"技工".equals(wordVO.getWords()) && !"工日".equals(wordVO.getWords())){
//                    Map<String,Double> map = new HashMap<>();
//                    map.put(codeVO.get(index++).getWords(),Double.valueOf(wordVO.getWords()));
//                    maps.add(map);
//                }
//            }
            return new CommonVO<>("200","success",vos);
        } catch (Exception e) {
            throw new CustomParameterizedException(e.getMessage());
        }
    }
}
